package com.herui.sdyu_lib.aliyun.oss;

import android.util.Log;

import com.alibaba.sdk.android.oss.ClientException;
import com.alibaba.sdk.android.oss.ServiceException;
import com.alibaba.sdk.android.oss.internal.OSSAsyncTask;
import com.alibaba.sdk.android.oss.model.GetObjectRequest;
import com.alibaba.sdk.android.oss.model.GetObjectResult;
import com.alibaba.sdk.android.oss.model.PutObjectRequest;
import com.alibaba.sdk.android.oss.model.PutObjectResult;
import com.alibaba.sdk.android.oss.model.Range;
import com.herui.sdyu_lib.http.callback.Callback;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.util.Map;


/**
 * Created by amanda.shan on 2016/7/20.
 */
public class AliOssUtils {

    /**
     * 多文件提交
     *
     * @param files
     * @param callback
     */
    public void putMutilAsyn(Map<String, String> files, Callback.CommonCallback<Void> callback) {
        String[] keyStrings = files.keySet().toArray(new String[0]);
        if (keyStrings != null)
            putRecursion(0, keyStrings, files, callback);
        else
            callback.onError(null, null, "map里面没有key");
    }

    /**
     * 递归上传
     *
     * @param index
     * @param keyStrings
     * @param files
     * @param callback
     */
    private void putRecursion(final int index, final String[] keyStrings, final Map<String,
            String> files,
                              final Callback.CommonCallback<Void> callback) {
        if (index == keyStrings.length)
            callback.onSuccess(null);
        else {
            putAsyn(keyStrings[index], files.get(keyStrings[index]), new Callback
                    .CommonCallback<Void>() {
                @Override
                public void onSuccess(Void result) {
                    int i = index + 1;
                    putRecursion(i, keyStrings, files, callback);
                }

                @Override
                public void onError(Throwable e, String code, String message) {
                    callback.onError(e, code, message);
                }
            });
        }
    }

    /**
     * 异步上传文件到阿里云
     *
     * @param objectKey
     * @param filePath
     * @param callback
     * @return task.cancel(); // 可以取消任务
     * task.waitUntilFinished(); // 可以等待任务完成
     */
    public OSSAsyncTask putAsyn(String objectKey, String filePath, Callback.CommonCallback<Void>
            callback) {

        // 构造上传请求
        PutObjectRequest put = new PutObjectRequest(AliOssConfig.bucketName, objectKey, filePath);

        // 异步上传时可以设置进度回调
        if (callback instanceof Callback.ProgressUpCallback)
            put.setProgressCallback(new OssCallBack.ProgressCallBack((Callback
                    .ProgressUpCallback<Void>) callback));

        OSSAsyncTask task = AliOssApp.getInstance().getOss().asyncPutObject(put, new
                OssCallBack.CompletedCallback(callback));

        return task;
    }


    /**
     * 同步上传文件
     *
     * @param objectKey
     * @param filePath
     * @return
     */
    public boolean put(String objectKey, String filePath) {
        // 构造上传请求
        PutObjectRequest put = new PutObjectRequest(AliOssConfig.bucketName, objectKey, filePath);

        // 文件元信息的设置是可选的
        // ObjectMetadata metadata = new ObjectMetadata();
        // metadata.setContentType("application/octet-stream"); // 设置content-type
        // metadata.setContentMD5(BinaryUtil.calculateBase64Md5(uploadFilePath)); // 校验MD5
        // put.setMetadata(metadata);

        try {

            PutObjectResult putResult = AliOssApp.getInstance().getOss().putObject(put);

            Log.d("PutObject", "UploadSuccess");
            Log.d("ETag", putResult.getETag());
            Log.d("RequestId", putResult.getRequestId());
            return true;
        } catch (ClientException e) {
            // 本地异常如网络异常等
            e.printStackTrace();
            return false;
        } catch (ServiceException e) {
            // 服务异常
            Log.e("RequestId", e.getRequestId());
            Log.e("ErrorCode", e.getErrorCode());
            Log.e("HostId", e.getHostId());
            Log.e("RawMessage", e.getRawMessage());
            return false;
        }
    }

    /**
     * 从阿里云下载文件
     *
     * @param objectKey
     * @return
     */
    public InputStream get(String objectKey) throws ClientException, ServiceException {
        GetObjectRequest get = new GetObjectRequest(AliOssConfig.bucketName, objectKey);

//        try {
        // 同步执行下载请求，返回结果
        GetObjectResult getResult = AliOssApp.getInstance().getOss().getObject(get);

        Log.d("Content-Length", "" + getResult.getContentLength());

        // 获取文件输入流
        InputStream inputStream = getResult.getObjectContent();
        return inputStream;
    }

    /**
     * 同步下载文件监听进度
     *
     * @param objectKey
     * @param filePath
     * @param callback
     * @return
     */
    public boolean getFileSyn(String objectKey, String filePath, Callback.ProgressDownCallback<Void>
            callback) {
        GetObjectRequest get = new GetObjectRequest(AliOssConfig.bucketName, objectKey);
        GetObjectResult getResult = null;

        try {
            getResult = AliOssApp.getInstance().getOss().getObject(get);
            if (getResult == null) {
                return false;
            }

            // 请求成功
            InputStream inputStream = getResult.getObjectContent();

            File file = new File(filePath);
            file.delete();

            try {
                OutputStream outputStream = new FileOutputStream(filePath);
                byte[] bytes = new byte[2000];
                int count = 0;
                int current = 0;
                while ((count = inputStream.read(bytes)) > 0) {
                    outputStream.write(bytes, 0, count);
                    current += count;

                    if (callback != null)
                        callback.onDownLoading(getResult.getContentLength(), current, current ==
                                getResult.getContentLength());
                }
                outputStream.close();
                inputStream.close();

                return true;
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } catch (ClientException e) {
            e.printStackTrace();
        } catch (ServiceException e) {
            e.printStackTrace();
        }

        return false;
    }


    private boolean runGetFileSyn;

    /**
     * 停止文件下载
     *
     * @param runGetFileSyn
     */
    public void stopDownloadFile(boolean runGetFileSyn) {
        this.runGetFileSyn = runGetFileSyn;
    }

    /**
     * 断点下载
     *
     * @param objectKey
     * @param rwd       文件写入对象  seek
     * @param start     下载开始位置
     * @param end       下载结束位置
     * @param callback  进度回调
     * @return
     */
    public boolean getFileSyn(String objectKey, RandomAccessFile rwd, int start, int end, Callback
            .ProgressDownCallback<Void> callback) {
        GetObjectRequest get = new GetObjectRequest(AliOssConfig.bucketName, objectKey);
        // 获取start~end字节范围内的数据
        get.setRange(new Range(start, end));

        GetObjectResult getResult = null;

        try {
            getResult = AliOssApp.getInstance().getOss().getObject(get);
            if (getResult == null) {
                return false;
            }

            // 请求成功
            InputStream inputStream = getResult.getObjectContent();

            try {
                byte[] bytes = new byte[2000];
                int count = 0;
                int current = 0;
                runGetFileSyn = true;
                while ((count = inputStream.read(bytes)) > 0 && runGetFileSyn) {
                    if (rwd != null)
                        rwd.write(bytes, 0, count);
                    current += count;

                    if (callback != null)
                        callback.onDownLoading(getResult.getContentLength(), current, current ==
                                getResult.getContentLength());
                }

                if (callback != null && !runGetFileSyn)
                    callback.onDownLoading(getResult.getContentLength(), current, current ==
                            getResult.getContentLength());

                if (rwd != null)
                    rwd.close();
                inputStream.close();

                return true;
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } catch (ClientException e) {
            e.printStackTrace();
        } catch (ServiceException e) {
            e.printStackTrace();
        }

        return false;
    }
}
